home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / fish / 001-100 / 001-025 / 004 / kermit / utils.c < prev    next >
C/C++ Source or Header  |  1995-03-17  |  12KB  |  520 lines

  1. /*    @(#)utils.c    1.1    1/26/85    */
  2.  
  3. #include "kermit.h"
  4.  
  5. #ifndef AMIGA
  6. #  include <setjmp.h>
  7. #  include <signal.h>
  8. #endif    /* !AMIGA */
  9.  
  10. static jmp_buf env;        /* Environment */
  11. static unsigned int timint;    /* Timeout for foreign host on sends */
  12.  
  13. /*
  14.  *    Library externals.
  15.  */
  16.  
  17. #ifdef unix
  18. extern unsigned alarm ();
  19. #endif
  20. extern VOID longjmp ();
  21.  
  22. /*
  23.  *      Various KERMIT utilities.
  24.  */
  25.  
  26.  
  27. clkint ()
  28. {                /* timer interrupt handlr */
  29.     longjmp (env, TRUE);    /* tell rpack to give up */
  30. }
  31.  
  32. /*
  33.  *    tochar converts a control character to a printable one by adding
  34.  *    a space
  35.  */
  36.  
  37. #ifndef tochar
  38. char tochar (ch)
  39. char ch;
  40. {
  41.     return (ch + ' ');        /* make sure not a control char */
  42. }
  43. #endif
  44.  
  45.  
  46. /*
  47.  *    unchar undoes tochar
  48.  */
  49.  
  50. #ifndef unchar
  51. char unchar (ch)
  52. char ch;
  53. {
  54.     return (ch - ' ');        /* restore char */
  55. }
  56. #endif
  57.  
  58. /*
  59.  * ctl turns a control character into a printable character by toggling the
  60.  * control bit (ie. ^A becomes A and A becomes ^A).
  61.  */
  62.  
  63. #ifndef ctl
  64. char ctl (ch)
  65. char ch;
  66. {
  67.     return (ch ^ 0100);        /* toggle the control bit */
  68. }
  69. #endif
  70.  
  71. /*
  72.  *      s p a c k
  73.  */
  74.  
  75. VOID spack (type, num, len, data)
  76. char type;
  77. char *data;
  78. int num;
  79. int len;
  80. {
  81.     int i;
  82.     char chksum;
  83.     char buffer[100];
  84.     register char *bufp;
  85.  
  86.     bufp = buffer;
  87.     /* issue necessary padding */
  88.     for (i = 1; i <= pad; i++) {
  89.     (VOID) write (remfd, &padchar, (unsigned int)1);
  90.     }
  91.     *bufp++ = SOH;            /* packet marker, ASCII 1 (SOH) */
  92.     chksum = tochar (len + 3);        /* initialize the checksum */
  93.     *bufp++ = tochar (len + 3);        /* send the character count */
  94.     chksum = chksum + tochar (num);    /* ini checksum */
  95.     *bufp++ = tochar (num);        /* packet number */
  96.     chksum = chksum + type;
  97.     *bufp++ = type;            /* packet type */
  98.  
  99.     /* loop for all data characters */
  100.     for (i = 0; i < len && i < (MAXPACK - 1); i++) {
  101.     *bufp++ = data[i];
  102.     chksum = chksum + data[i];
  103.     }
  104.     chksum = (((chksum >> 6) & 3) + chksum) & 077;
  105.     *bufp++ = tochar (chksum);        /* checksum */
  106.     *bufp = eol;            /* extra packet line terminator */
  107.     (VOID) write (remfd, buffer, (unsigned int) (bufp - buffer + 1));
  108.     if (tflg) {
  109.     printf ("%c", type);
  110.     fflush (stdout);
  111.     }
  112. }
  113.  
  114. /*
  115.  *     r p a c k
  116.  */
  117.  
  118. char rpack (len, num, data)
  119. int *len;
  120. int *num;
  121. char *data;
  122. {
  123.     int i;
  124.     int fld;
  125.     char chksum;
  126.     auto char inchar;
  127.     char type;
  128.  
  129.     DBUG_ENTER ("rpack");
  130.     DBUG_2 ("rcv", "beginning packet receive");
  131.     i = 0;
  132.     chksum = 0;
  133.     inchar = 0;
  134. #ifdef unix
  135.     if (setjmp (env)) {
  136.     DBUG_2 ("timeout", "read timed out");
  137.     if (tflg) {
  138.         printf ("T");
  139.         fflush (stdout);
  140.     }
  141.     DBUG_RETURN (FALSE);
  142.     }
  143.     (VOID) signal (SIGALRM, clkint);
  144.     if ((timint > MAXTIM) || (timint < MINTIM)) {
  145.     timint = MYTIME;
  146.     }
  147.     (VOID) alarm (timint);
  148. #endif
  149.     DBUG_3 ("rfd", "reading from fildes %d", remfd);
  150.     while (inchar != SOH) {
  151.     DBUG_3 ("read", "looking for SOH (%x)", (int) SOH);
  152.     (VOID) read (remfd, &inchar, 1);
  153.     DBUG_3 ("read", "read got '%x'", (int) inchar);
  154.     }
  155.     DBUG_2 ("SOH", "found packet header");
  156.     for (fld = 1; fld <= 5; fld++) {
  157.     DBUG_3 ("fld", "current fld %d", fld);
  158.     if (fld != 5 || i != 0) {        /* no char or no data */
  159.         DBUG_3 ("read", "read from %d", remfd);
  160.         (VOID) read (remfd, &inchar, 1);
  161.         DBUG_3 ("read", "read got %3.3o", inchar);
  162.         if (inchar == SOH) {
  163.         DBUG_2 ("resync", "found SOH, resync");
  164.         fld = 0;            /* resynch if SOH */
  165.         if (tflg) {
  166.             printf ("R");
  167.             fflush (stdout);
  168.         }
  169.         }
  170.     }
  171.     DBUG_3 ("fld", "process field %d", fld);
  172.     if (fld <= 3) {
  173.         chksum = chksum + inchar;        /* accumulate checksum */
  174.     }
  175.     switch (fld) {
  176.         case 0: 
  177.         chksum = 0;
  178.         break;                /* restart loop */
  179.         case 1: 
  180.         *len = unchar (inchar) - 3;
  181.         DBUG_3 ("rcv", "count %d", *len);
  182.         break;                /* character count */
  183.         case 2: 
  184.         *num = unchar (inchar);
  185.         DBUG_3 ("rcv", "packet %d", *num);
  186.         break;                /* packet number */
  187.         case 3: 
  188.         type = inchar;
  189.         DBUG_3 ("rcv", "type '%c'", type);
  190.         break;                /* packet type */
  191.         case 4: 
  192.         for (i = 0; i < *len && i < (MAXPACK - 1); i++) {
  193.             if (i != 0) {
  194.             (VOID) read (remfd, &inchar, 1);
  195.             if (inchar == SOH) {    /* get a char */
  196.                 fld = -1;
  197.                 break;
  198.             }
  199.             }
  200.             chksum = chksum + inchar;    /* add it to checksum */
  201.             data[i] = inchar;        /* normal character */
  202.         }
  203.         if (i < (MAXPACK - 1) && *len >= 0) {
  204.             data[*len] = 0;
  205.         } else {
  206.             data[0] = 0;
  207.         }
  208.         DBUG_3 ("rcv", "data \"%s\"", data);
  209.         break;
  210.         case 5: 
  211.         chksum = (((chksum >> 6) & 3) + chksum) & 077;
  212.         DBUG_3 ("chk", "checksum %d", chksum);
  213.         break;
  214.     }
  215.     }
  216. #ifdef unix
  217.     (VOID) alarm (0);                /* disable timer interrupt */
  218. #endif
  219.     if (chksum != unchar (inchar)) {        /* check the checksum */
  220.     printf ("X");
  221.     DBUG_4 ("chk", "checksum %o, should be %o", inchar, tochar (chksum));
  222.     DBUG_RETURN (FALSE);
  223.     }
  224.     DBUG_3 ("rcv", "got %c packet", type);
  225.     if (tflg) {
  226.     printf ("%c", type);
  227.     fflush (stdout);
  228.     }
  229.     DBUG_RETURN (type);                /* return packet type */
  230. }
  231.  
  232. /*
  233.  *      b u f i l l
  234.  */
  235.  
  236. int bufill (buffer)
  237. char buffer[];
  238. {
  239.     int i;
  240.     char inchar;
  241.  
  242.     DBUG_ENTER ("bufill");
  243.     i = 0;                    /* init data buffr pointr */
  244.     while (read (fd, &inchar, 1) > 0) {        /* get the next character */
  245.     inchar = inchar & 0177;
  246.     if (inchar < SP || inchar == DEL || inchar == quote) {
  247.         if (inchar == '\n') {        /* newline, squeeze CR */
  248.         buffer[i++] = quote;
  249.         buffer[i++] = ctl ('\r');
  250.         }
  251.         buffer[i++] = quote;
  252.         if (inchar != quote)
  253.         inchar = ctl (inchar);
  254.     }
  255.     buffer[i++] = inchar;
  256.     if ((i >= spsiz - 8) || (i >= MAXPACK - 8)) {
  257.         DBUG_RETURN (i);
  258.     }
  259.     }
  260.     if (i == 0) {
  261.     i = EOF;
  262.     }
  263.     DBUG_RETURN (i);
  264. }
  265.  
  266. /*
  267.  *    b u f e m p
  268.  */
  269.  
  270. VOID bufemp (buffer, ifd, len)
  271. char buffer[];
  272. int ifd;
  273. int len;
  274. {
  275.     int i;
  276.     char outchar;
  277.  
  278.     DBUG_ENTER ("bufemp");
  279.     DBUG_4 ("buf", "ifd %d  len %d", ifd, len);
  280.     for (i = 0; i < len; i++) {
  281.     outchar = buffer[i];
  282.     if (outchar == MYQUOTE) {
  283.         outchar = buffer[++i];
  284.         if (outchar != MYQUOTE) {
  285.         outchar = ctl (outchar);
  286.         }
  287.     }
  288.     if (outchar != 015) {            /* don't pass CR */
  289.         (VOID) write (ifd, &outchar, 1);
  290.     }
  291.     }
  292.     DBUG_VOID_RETURN;
  293. }
  294.  
  295.  
  296. /*
  297.  *      g e t f i l
  298.  */
  299.  
  300. int getfil (filenm)
  301. char *filenm;
  302. {
  303.     DBUG_ENTER ("getfil");
  304.     if (filenm[0] == '\0') {
  305.     fd = creat (packet, 0644);    /* if filename known, use it */
  306.     } else {
  307.     fd = creat (filenm, 0644);    /* else use sourcefile name */
  308.     }
  309.     DBUG_RETURN (fd > 0);        /* return false if fle won't open */
  310. }
  311.  
  312. /*
  313.  *      g n x t f l
  314.  */
  315.  
  316. int gnxtfl ()
  317. {
  318.     register int rtnval;
  319.     
  320.     DBUG_ENTER ("gnxtfl");
  321.     filnam = *(filelist++);
  322.     if (filnam == 0) {
  323.     rtnval = FALSE;
  324.     } else {
  325.     rtnval = TRUE;
  326.     }
  327.     DBUG_RETURN (rtnval);
  328. }
  329.  
  330. /*
  331.  *    spar fills the data array with appropriate send-init paramaters
  332.  */
  333.  
  334. VOID spar (data)
  335. char data[];
  336. {
  337.     data[0] = tochar (MAXPACK);    /* biggest packet I can receive */
  338.     data[1] = tochar (MYTIME);    /* when I want to be timed out */
  339.     data[2] = tochar (MYPAD);    /* how much padding I need */
  340.     data[3] = ctl (MYPCHAR);    /* padding characer I want */
  341.     data[4] = tochar (MYEOL);    /* end-o-line character I want */
  342.     data[5] = MYQUOTE;        /* quot character I send */
  343. }
  344.  
  345.  
  346. /*
  347.  *    rpar gets the other host's send-init parameters
  348.  */
  349.  
  350. VOID rpar (data)
  351. char data[];
  352. {
  353.     spsiz = unchar (data[0]);    /* maximum send packe size */
  354.     timint = unchar (data[1]);    /* when I should time out */
  355.     pad = unchar (data[2]);    /* number of pads to send */
  356.     padchar = ctl (data[3]);    /* padding character to send */
  357.     eol = unchar (data[4]);    /* EOL character I must send */
  358.     quote = data[5];        /* incoming data quote char */
  359. }
  360.  
  361. /*
  362.  *  NAME
  363.  *
  364.  *    tolower --- convert an alpha character to lowercase
  365.  *
  366.  *  KEY WORDS
  367.  *
  368.  *    extension libraries
  369.  *    tolower
  370.  *    character functions
  371.  *
  372.  *  DESCRIPTION
  373.  *
  374.  *    Converts an alpha character to lowercase.
  375.  *
  376.  *  USAGE
  377.  *
  378.  *    char tolower(ch)
  379.  *    char ch;
  380.  *
  381.  *  RETURNED VALUE(S)
  382.  *
  383.  *    If the input character is an alphabetic character then tolower
  384.  *    returns the lowercase version of that character.  Otherwise
  385.  *    it simply returns the character passed to it.
  386.  *
  387.  *  PROGRAMMER
  388.  *
  389.  *    Fred Fish
  390.  *    Tempe, Az 85281
  391.  *    (602) 966-8871
  392.  *
  393.  *  INTERNALS
  394.  *
  395.  *    Since the possibility exists that the native character set may
  396.  *    not be ASCII, "tolower" maintains an internal table of the characters
  397.  *    which it considers to be alphabetic, along with their mappings to
  398.  *    lowercase.
  399.  *
  400.  */
  401.  
  402. #ifndef unix
  403. static char *alphas[] = {
  404.     "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz"
  405. };
  406.  
  407. char tolower (ch)
  408. char ch;
  409. {
  410.     char *chp;
  411.  
  412.     chp = alphas[0];
  413.     while (*chp != NULL) {
  414.     if (*chp++ == ch) {
  415.         return (*chp);
  416.     } else {
  417.         chp++;
  418.     }
  419.     }
  420.     return (ch);
  421. }
  422. #endif
  423.  
  424. #ifdef AMIGA
  425. /* this is the public domain getopt from Usenet -- why re-invent the wheel? */
  426.  
  427. /*
  428. From: keith@seismo.UUCP (Keith Bostic)
  429.  
  430.                             23 Aug 84
  431. In April of this year, Henry Spencer (utzoo!henry) released a public
  432. domain version of getopt (USG, getopt(3)).  Well, I've been trying to
  433. port some USG dependent software and it didn't seem to work.  The problem
  434. ended up being that the USG version of getopt has some external variables
  435. that aren't mentioned in the documentation.  Anyway, to fix these problems,
  436. I rewrote the public version of getopt.  It has the following advantages:
  437.  
  438.     -- it includes those "unknown" variables
  439.     -- it's smaller/faster 'cause it doesn't use the formatted
  440.         output conversion routines in section 3 of the UNIX manual.
  441.     -- the error messages are the same as S5's.
  442.     -- it has the same side-effects that S5's has.
  443.     -- the posted bug on how the error messages are flushed has been
  444.         implemented.  (posting by Tony Hansen; pegasus!hansen)
  445.  
  446. I won't post the man pages since Henry already did; a special note,
  447. it's not documented in the S5 manual that the options ':' and '?' are
  448. illegal.  It should be obvious, but I thought I'd mention it...
  449. This software was derived from binaries of S5 and the S5 man page, and is
  450. (I think?) totally (I'm pretty sure?) compatible with S5 and backward
  451. compatible to Henry's version.
  452.  
  453.         Keith Bostic
  454.             ARPA: keith@seismo 
  455.             UUCP: seismo!keith
  456.  
  457. *UNIX is a trademark of Bell Laboratories
  458. */
  459.  
  460. /*
  461.  * get option letter from argument vector
  462.  */
  463.  
  464. /*
  465.  * ADR, 8/7/85 -- opterr if set to 0 disables the printing of
  466.  * error messages. Fixed this code to reflect that
  467.  */
  468.  
  469. int    opterr = 1,        /* do or don't print the error message */
  470.     optind = 1,        /* index into parent argv vector */
  471.     optopt;            /* character checked for validity */
  472. char    *optarg;        /* argument associated with option */
  473.  
  474. #define BADCH    (int)'?'
  475. #define EMSG    ""
  476. #define tell(msg) if (opterr) { fprintf (stderr, "%s%s%c\n", *nargv, msg, \
  477.         (char) optopt); } else /* no ; */
  478.         /* ADR, changed to used fprintf, not fputs */
  479.  
  480. getopt(nargc,nargv,ostr)
  481. int    nargc;
  482. char    **nargv,
  483.     *ostr;
  484. {
  485.     static char    *place = EMSG;    /* option letter processing */
  486.     register char    *oli;        /* option letter list index */
  487.     char    *strchr();        /* ADR -- was index */
  488.  
  489.     if(!*place) {            /* update scanning pointer */
  490.         if(optind >= nargc || *(place = nargv[optind]) != '-'
  491.                 || !*++place)
  492.             return(EOF);
  493.         if (*place == '-') {    /* found "--" */
  494.             ++optind;
  495.             return(EOF);
  496.         }
  497.     }                /* option letter okay? */
  498.     if ((optopt = (int)*place++) == (int)':' || !(oli = strchr(ostr,optopt))) {
  499.         if(!*place) ++optind;
  500.         tell(": illegal option -- ");
  501.     }
  502.     if (*++oli != ':') {        /* don't need argument */
  503.         optarg = NULL;
  504.         if (!*place) ++optind;
  505.     }
  506.     else {                /* need an argument */
  507.         if (*place) optarg = place;    /* no white space */
  508.         else if (nargc <= ++optind) {    /* no arg */
  509.             place = EMSG;
  510.             tell(": option requires an argument -- ");
  511.         }
  512.          else optarg = nargv[optind];    /* white space */
  513.         place = EMSG;
  514.         ++optind;
  515.     }
  516.     return(optopt);            /* dump back option letter */
  517. }
  518.  
  519. #endif    /* AMIGA */
  520.